/**
 * http 请求封装
 * @author tangsj
 * @param {*} url 请求地址
 * @param {*} options 请求参数
 */
import config from "../config"
import utils from "../utils"
import store from "@/store"
import api from "@/api"
import { removeUserToken, setUserToken, getUserToken } from "@/utils/auth"

// 记录请求中的请求数，控制loading显示
let requestCount = 0
let hasError = false
let isRefreshing = false // 是否正在刷新 Token
let requestsQueue = [] // 用于存储等待刷新 Token 的请求队列

export function fetch(url, options) {
  let header = {
    Authorization: `Bearer ${getUserToken()}`,
    // ContentType: "application/x-www-form-urlencoded",
  }

  options = Object.assign(
    {
      loading: true,
      method: "GET",
      data: {},
      holdTip: false,
    },
    options
  )

  return new Promise((resolve, reject) => {
    if (requestCount === 0 && options.loading) {
      hasError = false
    }

    requestCount += 1

    const requestTask = uni.request({
      url: `${config.apiRoot}${url}`,
      data: options.data,
      method: options.method,
      header,
      success: (res) => {
        // console.log(res)
        requestCount -= 1
        if (res.data.code === 200) {
          resolve(res.data || {})
        } else if (res.data.code === 401 && getUserToken()) {
          // Token 过期
          if (!isRefreshing) {
            isRefreshing = true
            // 将当前请求加入队列
            requestsQueue.push({ url, options, resolve, reject })
            // 调用刷新 Token 的接口
            uni.request({
              method: "POST",
              url: `https://zxsd-api.baibaitan.com/app-api/member/auth/refresh-token?refreshToken=${store.getters.refresh_token}`,
              success: (res) => {
              // 这里即使是 401 也会进来
                console.log("Token 刷新成功", res)
                if (res.data.code === 200) {
                  // 更新 Token
                  store.commit("SET_TOKEN", res.data.data.accessToken)
                  setUserToken(res.data.data.accessToken)
                  store.commit("SET_REFRESH_TOKEN",res.data.data.refreshToken)
                  // 重新发起队列中的请求
                  requestsQueue.forEach((req) => {
                    fetch(req.url, req.options)
                      .then(req.resolve)
                      .catch(req.reject)
                  })
                  // 清空队列
                  requestsQueue = []
                } else {
                  removeUserToken()
                  uni.navigateTo({ url: "/pages/authorization/index" })
                  uni.showToast({
                    title: "登录失效，请重新登录",
                    icon: "none",
                  })
                }
                isRefreshing = false
              },
              fail: (err) => {
                // 只有断网、DNS 错误等才会进这里
              }
            });
            return
          } else {
            // 如果已经在刷新 Token，将当前请求加入队列
            requestsQueue.push({ url, options, resolve, reject })
          }
        } else {
          // 其他错误
          resolve(res.data || {})
        }
      },
      fail: (err) => {
        console.log(err)
        requestCount -= 1
        hasError = true

        uni.showToast({
          title: "服务器异常！",
          icon: "none",
        })

        reject({
          msg: "服务器异常！",
        })
      },
      complete: () => {
        
      },
    })

    // 如果没有加载提示，且请求失败，直接显示错误
    if (!options.loading && hasError) {
      uni.showToast({
        title: "请求失败，请稍后再试",
        icon: "none",
      })
    }
  })
}

const http = {
  get(url, data = {}, options = {}) {
    return fetch(url, {
      method: "GET",
      data: data.params,
      ...options,
    })
  },
  put(url, data = {}, options = {}) {
    return fetch(url, {
      method: "PUT",
      data: data.params,
      ...options,
    })
  },
  delete(url, data = {}, options = {}) {
    return fetch(url, {
      method: "DELETE",
      data: data.params,
      ...options,
    })
  },
  post(url, data = {}, options = {}) {
    if (data.params) {
      // 将param放到url 参数里面
      const query = utils.buildQueryString(data.params)
      url += `?${query}`
      delete data.params
    }
    return fetch(url, {
      method: "POST",
      data,
      ...options,
    })
  },
}

export default http
